package com.lengxf.job.dynamicTask;

import cn.hutool.core.convert.ConverterRegistry;
import com.lengxf.job.dynamicTask.finder.TaskFinder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledFuture;

@Slf4j
@Component
public class DynamicTaskService {

    /**
     * 以下两个都是线程安全的集合类。
     */
    public Map<String, ScheduledFuture<?>> taskMap = new ConcurrentHashMap<>();

    /**
     * 查看已开启但还未执行的动态任务
     */
    @Getter
    public List<String> taskList = new CopyOnWriteArrayList<>();


    private final ThreadPoolTaskScheduler syncScheduler;

    private final TaskFinder taskFinder;

    public DynamicTaskService(ThreadPoolTaskScheduler syncScheduler, TaskFinder taskFinder) {
        this.syncScheduler = syncScheduler;
        this.taskFinder = taskFinder;
    }


    /**
     * 添加一个动态任务
     */
    public boolean add(Task task) {
        if (null != taskMap.get(task.getName())) {
            stop(task);
        }
        ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
        Instant startTime = converterRegistry.convert(Instant.class, task.getStartTime());
        //如果新增的定时任务开启时间早于当前时间 那此定时任务会被立即执行
        ScheduledFuture<?> schedule = syncScheduler.schedule(getRunnable(task), startTime);
        taskMap.put(task.getName(), schedule);
        taskList.add(task.getName());
        return true;
    }


    /**
     * 运行任务
     */
    public Runnable getRunnable(Task task) {
        return () -> {
            try {
                DynamicTask dynamicTask = taskFinder.findTask(task);
                dynamicTask.executeTask(task);
            } catch (Exception e) {
                log.error(e.getMessage());
            } finally {
                remove(task.getName());
            }
        };
    }

    /**
     * 停止任务
     */
    public void stop(Task task) {
        if (null == taskMap.get(task.getName())) {
            return;
        }
        ScheduledFuture<?> scheduledFuture = taskMap.get(task.getName());
        scheduledFuture.cancel(true);
        remove(task.getName());
    }

    private void remove(String name) {
        taskMap.remove(name);
        taskList.remove(name);
    }

}

